
package com.jf.cloud.search.listener;

import cn.hutool.core.collection.CollUtil;
import cn.throwx.canal.gule.model.CanalBinLogResult;
import com.jf.cloud.api.combo.feign.ComboFeignClient;
import com.jf.cloud.api.group.feign.GroupFeignClient;
import com.jf.cloud.api.multishop.feign.IndexImgFeignClient;
import com.jf.cloud.api.product.feign.*;
import com.jf.cloud.api.seckill.feign.SeckillFeignClient;
import com.jf.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.jf.cloud.common.cache.constant.CacheNames;
import com.jf.cloud.common.cache.constant.GroupCacheNames;
import com.jf.cloud.common.cache.constant.ProductCacheNames;
import com.jf.cloud.common.cache.util.RedisUtil;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.constant.StatusEnum;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.product.bo.EsProductBO;
import com.jf.cloud.common.product.constant.SalesType;
import com.jf.cloud.common.product.constant.SpuType;
import com.jf.cloud.common.product.constant.SupplierSpuType;
import com.jf.cloud.common.product.vo.app.SkuAppVO;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.search.bo.SpuBO;
import com.jf.cloud.search.constant.EsIndexEnum;
import com.jf.cloud.search.util.EsSearchUtil;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author zz
 * @date 2020/11/13
 */
@Component
public class SpuCanalListener extends BaseCanalBinlogEventThrowExceptionProcessor<SpuBO> {

    private static final Logger log = LoggerFactory.getLogger(SpuCanalListener.class);

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private SpuFeignClient spuFeignClient;

    @Autowired
    private ComboFeignClient comboFeignClient;

    @Autowired
    private GiveawayFeignClient giveawayFeignClient;

    @Autowired
    private IndexImgFeignClient indexImgFeignClient;
    @Autowired
    private SkuFeignClient skuFeignClient;

    @Autowired
    private GroupFeignClient groupFeignClient;

    @Autowired
    private SeckillFeignClient seckillFeignClient;

    /**
     * 插入商品，此时插入es
     */
    @Override
    protected void processInsertInternal(CanalBinLogResult<SpuBO> result) {
        Long spuId = result.getPrimaryKey();
        RedisUtil.del(CacheNames.SPU_TOTAL_STOCK + spuId);
        ServerResponseEntity<EsProductBO> esProductResponse = productFeignClient.loadEsProductBO(spuId);
        if (esProductResponse.isFail()) {
            log.error("商品id为：{}的商品数据异常！", spuId);
            return;
        }
        EsProductBO esProductBO = esProductResponse.getData();
        if(!Objects.equals(esProductBO.getSpuType(), SpuType.SCORE.value())) {
            //平台分类名称
            ServerResponseEntity<String> categoryAllById = categoryFeignClient.getCategoryAllById(esProductBO.getCategoryId());
            esProductBO.setCategoryNames(categoryAllById.getData());
            if (Objects.isNull(esProductBO)) {
                log.error("商品id为：{}的商品数据为null！", spuId);
                return;
            }
        }
        if(Objects.nonNull(esProductBO.getSupplierSpuType()) && esProductBO.getSupplierSpuType().equals(1)){
            int sum=0;
            for (SkuAppVO skuAppVO : skuFeignClient.listBySpuId(esProductBO.getSpuId()).getData()) {
                sum+=skuAppVO.getStockWarning()==null?0:skuAppVO.getStockWarning();
            }
            esProductBO.setStockWarning(sum);
        }else {
            esProductBO.setStockWarning(0);
        }
        // 没有删除的商品保存，已删除的商品直接清除缓存
//        if (!Objects.equals(esProductBO.getSpuStatus(), StatusEnum.DELETE.value())) {
            //为团购商品获取商品活动最低价对应的sku原价
            if (esProductBO.getSpuType() == 1){
                //获取活动sku最低价
                Object priceFree = RedisUtil.get(CacheNames.GROUP_SPU_PRICE_FREE + esProductBO.getActivityId());
                if (!Objects.isNull(priceFree)){
                    esProductBO.setPriceFee(Long.valueOf(priceFree.toString()));
                    //移除
                    RedisUtil.del(CacheNames.GROUP_SPU_PRICE_FREE + esProductBO.getActivityId());
                }
            }
            EsSearchUtil.esSave(esProductBO.getSpuId(),EsIndexEnum.PRODUCT, esProductBO);
//        }
        removeCache(esProductBO);
    }

    /**
     * 更新商品，删除商品索引，再重新构建一个
     */
    @Override
    protected void processUpdateInternal(CanalBinLogResult<SpuBO> result) {
        SpuBO afterData = result.getAfterData();
        SpuBO beforeData = result.getBeforeData();
        handleStatusChange(afterData, beforeData.getStatus());
        if (!Objects.isNull(afterData.getPriceFee())){
            // 更新代销商品价格
            spuFeignClient.soldOutSpuBySpu(afterData.getSpuId(),afterData.getPriceFee(),afterData.getMarketPriceFee());
        }

        // 供应商品更新品牌或者排序时,需要同步更新代销商品的品牌或排序
        if (Objects.nonNull(beforeData.getBrandId()) || Objects.nonNull(beforeData.getSeq())){
            Long brandId = -1L;
            Integer seq = -1;
            if (Objects.nonNull(beforeData.getBrandId())){
                brandId = afterData.getBrandId();
            }
            if (Objects.nonNull(beforeData.getSeq())){
                seq = afterData.getSeq();
            }
            spuFeignClient.syncUpdateCommissionSpuBrandOrSeq(brandId,seq,afterData.getSpuId());
        }
        // 删除数据
        DeleteRequest request = new DeleteRequest(EsIndexEnum.PRODUCT.value(),String.valueOf(result.getPrimaryKey()));
        try {
            DeleteResponse deleteResponse = restHighLevelClient.delete(request,RequestOptions.DEFAULT);
            if (!Objects.isNull(beforeData.getStatus()) && Objects.equals(afterData.getSupplierSpuType(), SupplierSpuType.YES.value())){
                Object skuDelete = RedisUtil.get(ProductCacheNames.SKU_STATUS_DELETE + afterData.getSpuId());
                if (Objects.isNull(skuDelete)){
                    //供应商商品状态改变时同步改变商家发布的供应商品
                    spuFeignClient.supplierUpdateSpuStatus(afterData.getSpuId(),afterData.getStatus());
                }
            }
            // 如果是 分片/取消分片 的话不更新代销商品状态
            if (Objects.isNull(beforeData.getSkuZoned()) || Objects.equals(beforeData.getSkuZoned(), afterData.getSkuZoned())) {
                supplierUpdateSkuStatus(afterData,beforeData);
            }            log.info(deleteResponse.toString());
            // 保存es商品信息,删除的商品也要存一下，装修接口使用
            this.processInsertInternal(result);
        } catch (IOException e) {
            log.error(e.toString());
            throw new LuckException("更新es信息异常", e);
        }
    }

    /**
     * 清除商品关联的缓存
     * @param esProductBO
     */
    private void removeCache(EsProductBO esProductBO) {
        // keys不能使用Arrays.asList生成，Arrays.asList生成的ArrayList是内部类没有实现add方法
        List<String> keys = new ArrayList<>();
        keys.add(CacheNames.SKU_WITH_ATTR_LIST_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SKU_STOCK_LIST_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SPU_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SPU_EXTENSION_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SPU_DETAIL_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SPU_ATTR_VALUE_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(CacheNames.SPU_ACTIVITY_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(GroupCacheNames.GROUP_BY_SPU_KEY + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(ProductCacheNames.SPU_ZONE_STOCK + CacheNames.UNION + esProductBO.getSpuId());
        keys.add(ProductCacheNames.SPU_ZONE + CacheNames.UNION + esProductBO.getSpuId());
        if (CollUtil.isNotEmpty(esProductBO.getTagIds())) {
            keys.add(CacheNames.SPU_TAG_BY_SHOP + CacheNames.UNION + Constant.PLATFORM_SHOP_ID);
        }
        // 批量删除与商品关联的缓存信息
        RedisUtil.deleteBatch(keys);
    }

    /**
     * 商品状态发生改变时，需要处理的事件
     *
     * @param spuBO 修改后的商品数据
     * @param oldStatus 修改前的商品状态
     */
    private void handleStatusChange(SpuBO spuBO, Integer oldStatus) {
        // 状态没有发生改变或者不是变更未下线、下架、删除状态，则不进行处理
        if (Objects.isNull(oldStatus) || !StatusEnum.offlineStatus(spuBO.getStatus())) {
            return;
        }
        productFeignClient.handleStatusChange(spuBO.getSpuId());
        boolean isTrue = (Objects.equals(spuBO.getStatus(), StatusEnum.DISABLE.value()) || Objects.equals(spuBO.getStatus(), StatusEnum.OFFLINE.value()))
                && !Objects.equals(spuBO.getSpuType(), SpuType.SCORE.value());
        if (isTrue) {
            log.info("不是积分商品下架，处理相关活动", spuBO.getSpuId());
            //下架商品时如果商品在套餐活动中且为主商品则失效套餐活动,赠品同样
            comboFeignClient.offComboMainSpu(spuBO.getSpuId());
            giveawayFeignClient.changeGiveawayStatus(spuBO.getSpuId());
            // 失效拼团和秒杀活动
            groupFeignClient.updateGroupActivityStatus(spuBO.getSpuId());
            seckillFeignClient.offlineSeckillBySpuIds(Arrays.asList(spuBO.getSpuId()));
            //切换轮播图
            indexImgFeignClient.udpateIndexImgBySpuId(spuBO.getSpuId(), spuBO.getShopId());
        }
        giveawayFeignClient.changeGiveawaySpuStatus(spuBO.getSpuId());
        comboFeignClient.removeComboSpuCache(spuBO.getSpuId());

    }


    /**
     * 检查供应商sku状态是否改变，改变对代销商品进行下架
     */
    private void supplierUpdateSkuStatus(SpuBO afterData,SpuBO beforeData) {
        //供应商sku禁用状态是否改变
        Object enable = RedisUtil.get(ProductCacheNames.SKU_STATUS_ENABLE + afterData.getSpuId());
        Object disable = RedisUtil.get(ProductCacheNames.SKU_STATUS_DISABLE + afterData.getSpuId());
        Object skuDelete = RedisUtil.get(ProductCacheNames.SKU_STATUS_DELETE + afterData.getSpuId());
        if (Objects.isNull(enable) && Objects.isNull(disable)) {
            if (Objects.isNull(skuDelete)){
                //供应商变更了商品信息，下架手动设价的代销商品(价格变化不执行),商家自行发货的不下价
                if (Objects.isNull(beforeData.getPriceFee()) && Objects.isNull(beforeData.getMarketPriceFee())) {
                    spuFeignClient.soldOutManualPriceCommissionSpu(afterData.getSpuId(), SalesType.MANUAL_OPERATION_PRICE.value(),1);
                }
            }
            RedisUtil.del(ProductCacheNames.SKU_STATUS_DELETE + afterData.getSpuId());
        } else {
            if (!Objects.isNull(enable)) {
                //sku启用，下架手动设价
                spuFeignClient.soldOutManualPriceCommissionSpu(afterData.getSpuId(), SalesType.MANUAL_OPERATION_PRICE.value(),-1);
                RedisUtil.del(ProductCacheNames.SKU_STATUS_ENABLE + afterData.getSpuId());
                RedisUtil.del(ProductCacheNames.SKU_STATUS_DISABLE + afterData.getSpuId());
            }
        }
        RedisUtil.del(ProductCacheNames.SKU_STATUS_DELETE + afterData.getSpuId());
    }

}
